package com.autonavi.yunda.yunji.core.service;

import com.autonavi.yunda.yunji.common.exception.AmapException;
import com.autonavi.yunda.yunji.common.exception.AmapExceptionCode;
import com.autonavi.yunda.yunji.common.exception.AmapPreconditions;
import com.autonavi.yunda.yunji.core.code.generator.GroovyCodeGenerator;
import com.autonavi.yunda.yunji.core.config.EngineConstant;
import com.autonavi.yunda.yunji.core.engine.argresolver.ParamResolver;
import com.autonavi.yunda.yunji.core.engine.javascript.JsExecutor;
import com.autonavi.yunda.yunji.core.enums.NodeType;
import com.autonavi.yunda.yunji.core.vo.node.BaseNode;
import com.autonavi.yunda.yunji.core.vo.node.GroovyFunctionNode;
import com.autonavi.yunda.yunji.core.vo.node.JsFunctionNode;
import com.autonavi.yunda.yunji.core.vo.param.NodeParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * function节点参数列表-json字符串-groovy代码相互转换
 */
@Slf4j
@Component
public class CodeGenerateService {
    final private JsExecutor jsExecutor = new JsExecutor();

    /**
     * 通过页面传入的节点参数(json)转换成groovy代码并返回
     *
     * @param baseNode 节点参数
     * @return 代码
     */
    public String generateCode(BaseNode baseNode, String projectId) throws Exception {
        AmapPreconditions.checkArgumentForUser(Strings.isNotBlank(baseNode.name), "节点名称不能为空");
        String name = baseNode.name;
        if (baseNode.nodeType.equals(NodeType.groovy)) {
            String packageName = ((GroovyFunctionNode) baseNode).packageName;
            if (StringUtils.isEmpty(packageName)) {
                packageName = name;
            }
            GroovyFunctionNode node = (GroovyFunctionNode) baseNode;
            GroovyCodeGenerator generator = new GroovyCodeGenerator(
                    name,
                    node.script,
                    node.params,
                    convertPackageName(packageName),
                    projectId
            );
            return generator.toGroovyContent();
        } else if (baseNode.nodeType.equals(NodeType.javascript)) {
            JsFunctionNode node = (JsFunctionNode) baseNode;
            Map<String, Object> ps = new LinkedHashMap<>();
            for (NodeParam p : node.params) {
                if (p.debugValue != null) {
                    ps.put(p.getParamNameInScript(), ParamResolver.getParamValueByType(p.debugValue, p.type));
                }
            }
            return jsExecutor.mergeProperties(ps, node.script);
        } else {
            throw new AmapException(AmapExceptionCode.COMMON_ILLEGAL_PARAM, "暂不支持此节点类型的脚本生成");
        }
    }

    private String convertPackageName(String packageName) {
        String[] split = packageName.split("/");
        return Arrays.stream(split).map(item -> {
            if (EngineConstant.INVALID_VAR_NAME_SET.contains(item)) {
                return "__" + item;
            }
            return item;
        }).collect(Collectors.joining("."));
    }


}
